[IA64] Complete fpswa handler retry mechanism
authorawilliam@xenbuild.aw <awilliam@xenbuild.aw>
Tue, 26 Sep 2006 22:15:45 +0000 (16:15 -0600)
committerawilliam@xenbuild.aw <awilliam@xenbuild.aw>
Tue, 26 Sep 2006 22:15:45 +0000 (16:15 -0600)
When handling fpswa fault, Xen needs to fetch opcode, it may fail.
This patch finishes retry mechanism.

Signed-off-by: Anthony Xu <anthony.xu@intel.com>
xen/arch/ia64/vmx/vmx_process.c
xen/arch/ia64/vmx/vmx_vcpu.c
xen/include/asm-ia64/ia64_int.h
xen/include/asm-ia64/vmx_vcpu.h

index 7867fd399313937e649838239721090366996495..ad37920dc2ce01440b8599f6e1a3cec46997dd3b 100644 (file)
@@ -81,6 +81,7 @@ static UINT64 vec2off[68] = {0x0,0x400,0x800,0xc00,0x1000, 0x1400,0x1800,
 void vmx_reflect_interruption(UINT64 ifa,UINT64 isr,UINT64 iim,
      UINT64 vector,REGS *regs)
 {
+    UINT64 status;
     VCPU *vcpu = current;
     UINT64 vpsr = VCPU(vcpu, vpsr);
     vector=vec2off[vector];
@@ -89,13 +90,23 @@ void vmx_reflect_interruption(UINT64 ifa,UINT64 isr,UINT64 iim,
     }
     else{ // handle fpswa emulation
         // fp fault
-        if(vector == IA64_FP_FAULT_VECTOR && !handle_fpu_swa(1, regs, isr)){
-            vmx_vcpu_increment_iip(vcpu);
-            return;
+        if (vector == IA64_FP_FAULT_VECTOR) {
+            status = handle_fpu_swa(1, regs, isr);
+            if (!status) {
+                vmx_vcpu_increment_iip(vcpu);
+                return;
+            } else if (IA64_RETRY == status)
+                return;
         }
         //fp trap
-        else if(vector == IA64_FP_TRAP_VECTOR && !handle_fpu_swa(0, regs, isr)){
-            return; 
+        else if (vector == IA64_FP_TRAP_VECTOR) {
+            status = handle_fpu_swa(0, regs, isr);
+            if (!status)
+                return;
+            else if (IA64_RETRY == status) {
+                vmx_vcpu_decrement_iip(vcpu);
+                return;
+            }
         }
     }
     VCPU(vcpu,isr)=isr;
index e6824d3ec9806b2c6686a6f8dfd855113bb8e756..3d9c65a7f0c1daa71002f813ee3a1d8d744ddcd2 100644 (file)
@@ -172,6 +172,21 @@ IA64FAULT vmx_vcpu_increment_iip(VCPU *vcpu)
 }
 
 
+IA64FAULT vmx_vcpu_decrement_iip(VCPU *vcpu)
+{
+    REGS *regs = vcpu_regs(vcpu);
+    IA64_PSR *ipsr = (IA64_PSR *)&regs->cr_ipsr;
+    
+    if (ipsr->ri == 0) {
+        ipsr->ri = 2;
+        regs->cr_iip -= 16;
+    } else {
+        ipsr->ri--;
+    }
+    return (IA64_NO_FAULT);
+}
+
+
 IA64FAULT vmx_vcpu_cover(VCPU *vcpu)
 {
     REGS *regs = vcpu_regs(vcpu);
index 0bef5b4a1b27e661d144ac0f53f9c3907452c2b8..711078104bcd6513b7c99f8b005ae638137b012f 100644 (file)
@@ -36,7 +36,9 @@
 #define        IA64_NO_FAULT           0x0000
 #define IA64_FAULT                     0x0001
 #define        IA64_RFI_IN_PROGRESS    0x0002
-#define IA64_RETRY              0x0003
+// To avoid conflicting with return value of handle_fpu_swa()
+// set IA64_RETRY to -0x000f 
+#define IA64_RETRY             (-0x000f)
 #define IA64_FORCED_IFA         0x0004
 #define IA64_USE_TLB           0x0005
 #define        IA64_ILLOP_FAULT        (IA64_GENEX_VECTOR | 0x00)
index a82e31fb7f940f6b778124a37236e4401e7289e5..0a82cad583ca56a88490dabb39c35b6fbbeb6f63 100644 (file)
@@ -114,6 +114,7 @@ extern void memwrite_v(VCPU *vcpu, thash_data_t *vtlb, u64 *src, u64 *dest, size
 extern void memwrite_p(VCPU *vcpu, u64 *src, u64 *dest, size_t s);
 extern void vcpu_load_kernel_regs(VCPU *vcpu);
 extern IA64FAULT vmx_vcpu_increment_iip(VCPU *vcpu);
+extern IA64FAULT vmx_vcpu_decrement_iip(VCPU *vcpu);
 extern void vmx_switch_rr7(unsigned long ,shared_info_t*,void *,void *,void *);
 
 extern void dtlb_fault (VCPU *vcpu, u64 vadr);